package com.coursehub.course.service.impl;

import com.coursehub.course.dto.CourseCreateDto;
import com.coursehub.course.dto.CourseUpdateDto;
import com.coursehub.course.entity.Course;
import com.coursehub.course.entity.CourseTeacher;
import com.coursehub.course.entity.CourseTeacherId;
import com.coursehub.course.repository.CourseRepository;
import com.coursehub.course.repository.CourseStudentRepository;
import com.coursehub.course.repository.CourseTeacherRepository;
import com.coursehub.course.service.CourseService;
import com.coursehub.shared.exception.BusinessException;
import com.coursehub.shared.exception.ResourceNotFoundException;
import com.coursehub.shared.client.ServiceClient;
import com.coursehub.shared.util.StringUtils;
import lombok.RequiredArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

/**
 * 课程服务实现类
 */
@Service
@RequiredArgsConstructor
@Transactional
public class CourseServiceImpl implements CourseService {
    
    private static final Logger log = LoggerFactory.getLogger(CourseServiceImpl.class);
    
    private final CourseRepository courseRepository;
    private final CourseTeacherRepository courseTeacherRepository;
    private final CourseStudentRepository courseStudentRepository;
    private final ServiceClient serviceClient;
    
    @Override
    public Course createCourse(CourseCreateDto createDto) {
        log.info("创建课程: {}", createDto.getCourseName());
        
        // 验证课程名称是否已存在
        if (courseRepository.existsByCourseName(createDto.getCourseName())) {
            throw new BusinessException("课程名称已存在: " + createDto.getCourseName());
        }
        
        // 验证课程编号是否已存在（如果用户提供了课程编号）
        if (createDto.getCourseId() != null && !createDto.getCourseId().trim().isEmpty()) {
            if (courseRepository.existsByCourseId(createDto.getCourseId())) {
                throw new BusinessException("课程编号已存在: " + createDto.getCourseId());
            }
        }
        
        // 验证用户是否存在（调用用户服务）
        System.out.println("[DEBUG] 准备验证用户存在性: " + createDto.getUserId());
        if (!validateUserExists(createDto.getUserId())) {
            System.out.println("[DEBUG] 用户验证失败，抛出BusinessException");
            throw new BusinessException("用户不存在: " + createDto.getUserId());
        }
        System.out.println("[DEBUG] 用户验证成功，继续创建课程");
        
        // 创建课程实体
        Course course = new Course();
        // 使用用户输入的课程编号，如果没有提供则生成UUID
        String courseId = (createDto.getCourseId() != null && !createDto.getCourseId().trim().isEmpty()) 
                ? createDto.getCourseId().trim() 
                : UUID.randomUUID().toString();
        course.setCourseId(courseId);
        course.setCourseName(createDto.getCourseName());
        course.setCourse(createDto.getCourse());
        course.setTeachingGoal(createDto.getTeachingGoal());
        course.setExaminationMethod(createDto.getExaminationMethod());
        
        Course savedCourse = courseRepository.save(course);
        log.info("课程创建成功: {}", savedCourse.getCourseId());
        
        // 将创建者自动添加为课程教师
        try {
            log.info("[DEBUG] 开始将创建者添加为课程教师: courseId={}, userId={}", savedCourse.getCourseId(), createDto.getUserId());
            addTeacherToCourse(savedCourse.getCourseId(), createDto.getUserId());
            log.info("[DEBUG] 创建者已自动添加为课程教师: courseId={}, userId={}", savedCourse.getCourseId(), createDto.getUserId());
        } catch (Exception e) {
            log.error("[DEBUG] 添加创建者为教师失败: courseId={}, userId={}, 错误类型: {}, 错误信息: {}", 
                    savedCourse.getCourseId(), createDto.getUserId(), e.getClass().getSimpleName(), e.getMessage(), e);
            // 不抛出异常，因为课程已经创建成功
        }
        
        return savedCourse;
    }
    
    @Override
    @Transactional(readOnly = true)
    public Course getCourseById(String courseId) {
        return courseRepository.findById(courseId)
                .orElseThrow(() -> new ResourceNotFoundException("Course", courseId));
    }
    
    @Override
    @Transactional(readOnly = true)
    public List<Course> getAllCourses() {
        return courseRepository.findAll();
    }
    
    @Override
    public Course updateCourse(String courseId, CourseUpdateDto updateDto) {
        log.info("更新课程: {}", courseId);
        
        Course existingCourse = getCourseById(courseId);
        
        // 如果要更新课程名称，检查新名称是否已存在
        if (StringUtils.isNotBlank(updateDto.getCourseName()) && 
            !updateDto.getCourseName().equals(existingCourse.getCourseName())) {
            if (courseRepository.existsByCourseName(updateDto.getCourseName())) {
                throw new BusinessException("课程名称已存在: " + updateDto.getCourseName());
            }
        }
        
        // 更新课程信息
        if (StringUtils.isNotBlank(updateDto.getCourseName())) {
            existingCourse.setCourseName(updateDto.getCourseName());
        }
        if (updateDto.getCourse() != null) {
            existingCourse.setCourse(updateDto.getCourse());
        }
        if (updateDto.getTeachingGoal() != null) {
            existingCourse.setTeachingGoal(updateDto.getTeachingGoal());
        }
        if (StringUtils.isNotBlank(updateDto.getExaminationMethod())) {
            existingCourse.setExaminationMethod(updateDto.getExaminationMethod());
        }
        
        Course updatedCourse = courseRepository.save(existingCourse);
        log.info("课程更新成功: {}", courseId);
        
        return updatedCourse;
    }
    
    @Override
    public void deleteCourse(String courseId) {
        log.info("删除课程: {}", courseId);
        
        if (!courseRepository.existsByCourseId(courseId)) {
            throw new ResourceNotFoundException("Course", courseId);
        }
        
        courseRepository.deleteById(courseId);
        log.info("课程删除成功: {}", courseId);
    }
    
    @Override
    @Transactional(readOnly = true)
    public List<Course> searchCoursesByName(String courseName) {
        if (StringUtils.isBlank(courseName)) {
            return getAllCourses();
        }
        return courseRepository.findByCourseNameContaining(courseName.trim());
    }
    
    @Override
    @Transactional(readOnly = true)
    public List<Course> getCoursesByExaminationMethod(String examinationMethod) {
        if (StringUtils.isBlank(examinationMethod)) {
            return getAllCourses();
        }
        return courseRepository.findByExaminationMethod(examinationMethod.trim());
    }
    
    @Override
    @Transactional(readOnly = true)
    public boolean existsByCourseId(String courseId) {
        return StringUtils.isNotBlank(courseId) && courseRepository.existsByCourseId(courseId);
    }
    
    @Override
    @Transactional(readOnly = true)
    public boolean existsByCourseName(String courseName) {
        return StringUtils.isNotBlank(courseName) && courseRepository.existsByCourseName(courseName);
    }
    
    @Override
    @Transactional(readOnly = true)
    public List<Course> searchCourses(String courseName, String examinationMethod) {
        return courseRepository.findCoursesByConditions(courseName, examinationMethod);
    }
    
    @Override
    public boolean validateUserPermission(String userId, String courseId) {
        log.info("[DEBUG] 验证用户权限: userId={}, courseId={}", userId, courseId);
        
        if (StringUtils.isBlank(userId) || StringUtils.isBlank(courseId)) {
            log.warn("[DEBUG] 参数为空，权限验证失败: userId={}, courseId={}", userId, courseId);
            return false;
        }
        
        boolean userExists = validateUserExists(userId);
        if (!userExists) {
            log.warn("[DEBUG] 用户不存在，权限验证失败: userId={}", userId);
            return false;
        }
        
        boolean isTeacher = courseTeacherRepository.existsByCourseIdAndUserId(courseId, userId);
        boolean isStudent = courseStudentRepository.existsByCourseIdAndUserId(courseId, userId);
        boolean hasPermission = isTeacher || isStudent;
        
        log.info("[DEBUG] 权限验证结果: userId={}, courseId={}, isTeacher={}, isStudent={}, hasPermission={}",
                userId, courseId, isTeacher, isStudent, hasPermission);
        return hasPermission;
    }
    
    @Override
    @Transactional(readOnly = true)
    public List<String> getTeachersInCourse(String courseId) {
        log.info("[DEBUG] 开始获取课程教师列表: courseId={}", courseId);
        
        List<CourseTeacher> courseTeachers = courseTeacherRepository.findByCourse_CourseId(courseId);
        log.info("[DEBUG] 从数据库查询到的CourseTeacher记录数: courseId={}, count={}", courseId, courseTeachers.size());
        
        for (int i = 0; i < courseTeachers.size(); i++) {
            CourseTeacher ct = courseTeachers.get(i);
            log.info("[DEBUG] CourseTeacher[{}]: courseId={}, userId={}, id={}", 
                    i, ct.getId().getCourseId(), ct.getId().getUserId(), ct.getId());
        }
        
        List<String> teacherIds = courseTeachers.stream()
                .map(courseTeacher -> courseTeacher.getId().getUserId())
                .collect(java.util.stream.Collectors.toList());
        
        log.info("[DEBUG] 课程教师ID列表: courseId={}, teacherIds={}", courseId, teacherIds);
        return teacherIds;
    }
    
    @Override
    @Transactional(readOnly = true)
    public List<String> getStudentsInCourse(String courseId) {
        log.info("获取课程学生列表: {}", courseId);
        
        return courseStudentRepository.findStudentIdsByCourseId(courseId);
    }
    
    @Override
    public void addTeacherToCourse(String courseId, String userId) {
        log.info("[DEBUG] 开始添加教师到课程: courseId={}, userId={}", courseId, userId);
        
        // 验证课程是否存在
        log.info("[DEBUG] 验证课程是否存在: courseId={}", courseId);
        Course course = getCourseById(courseId);
        log.info("[DEBUG] 课程验证成功: courseId={}, courseName={}", courseId, course.getCourseName());
        
        // 验证用户是否存在
        log.info("[DEBUG] 验证用户是否存在: userId={}", userId);
        boolean userExists = validateUserExists(userId);
        log.info("[DEBUG] 用户存在性验证结果: userId={}, exists={}", userId, userExists);
        if (!userExists) {
            log.error("[DEBUG] 用户不存在，抛出异常: userId={}", userId);
            throw new BusinessException("用户不存在: " + userId);
        }
        
        // 检查教师是否已分配到该课程
        log.info("[DEBUG] 检查教师是否已分配到课程: courseId={}, userId={}", courseId, userId);
        boolean alreadyExists = courseTeacherRepository.existsByCourseIdAndUserId(courseId, userId);
        log.info("[DEBUG] 教师分配检查结果: courseId={}, userId={}, alreadyExists={}", courseId, userId, alreadyExists);
        if (alreadyExists) {
            log.error("[DEBUG] 教师已分配到该课程，抛出异常: courseId={}, userId={}", courseId, userId);
            throw new BusinessException("教师已分配到该课程: " + userId);
        }
        
        // 创建课程教师关联
        log.info("[DEBUG] 创建课程教师关联: courseId={}, userId={}", courseId, userId);
        CourseTeacherId courseTeacherId = new CourseTeacherId(userId, courseId);
        log.info("[DEBUG] 创建CourseTeacherId: {}", courseTeacherId);
        
        CourseTeacher courseTeacher = new CourseTeacher();
        courseTeacher.setId(courseTeacherId);
        courseTeacher.setCourse(course);
        log.info("[DEBUG] 创建CourseTeacher对象完成: courseId={}, userId={}", courseId, userId);
        
        // 在微服务架构中，我们只存储关联关系，不维护User实体
        
        log.info("[DEBUG] 保存课程教师关联到数据库: courseId={}, userId={}", courseId, userId);
        CourseTeacher savedCourseTeacher = courseTeacherRepository.save(courseTeacher);
        log.info("[DEBUG] 课程教师关联保存成功: courseId={}, userId={}, savedId={}", 
                courseId, userId, savedCourseTeacher.getId());
        
        // 验证保存结果
        boolean verifyExists = courseTeacherRepository.existsByCourseIdAndUserId(courseId, userId);
        log.info("[DEBUG] 保存后验证教师关联是否存在: courseId={}, userId={}, exists={}", 
                courseId, userId, verifyExists);
        
        log.info("[DEBUG] 教师添加成功: courseId={}, userId={}", courseId, userId);
    }
    
    @Override
    public void removeTeacherFromCourse(String courseId, String userId) {
        log.info("从课程中移除教师: courseId={}, userId={}", courseId, userId);
        
        // 验证课程是否存在
        if (!existsByCourseId(courseId)) {
            throw new ResourceNotFoundException("Course", courseId);
        }
        
        // 检查教师是否分配到该课程
        if (!courseTeacherRepository.existsByCourseIdAndUserId(courseId, userId)) {
            throw new BusinessException("教师未分配到该课程: " + userId);
        }
        
        courseTeacherRepository.deleteById_CourseIdAndId_UserId(courseId, userId);
        log.info("教师移除成功: courseId={}, userId={}", courseId, userId);
    }
    
    @Override
    @Transactional(readOnly = true)
    public List<Course> getCoursesByUserIdAndRole(String userId, String role) {
        log.info("根据用户ID和角色获取课程列表: userId={}, role={}", userId, role);
        
        if ("Teacher".equals(role) || "TEACHER".equals(role)||"teacher".equals(role)) {
            List<CourseTeacher> courseTeachers = courseTeacherRepository.findById_UserId(userId);
            log.info("查询到的教师课程关联数量: userId={}, count={}", userId, courseTeachers.size());
            List<Course> courses = courseTeachers.stream()
                    .map(CourseTeacher::getCourse)
                    .collect(Collectors.toList());
            log.info("返回的课程列表: userId={}, courses={}", userId, courses.size());
            return courses;
        }
        
        if ("Student".equals(role) || "STUDENT".equals(role)||"student".equals(role)) {
            // 学生角色的处理逻辑
            List<String> courseIds = courseStudentRepository.findCourseIdsByUserId(userId);
            return courseIds.stream()
                    .map(this::getCourseById)
                    .collect(Collectors.toList());
        }
        
        log.warn("未识别的角色类型: userId={}, role={}", userId, role);
        return List.of();
    }
    
    @Override
    public boolean isStudentEnrolledInCourse(String courseId, String studentId) {
        log.info("验证学生选课状态: courseId={}, studentId={}", courseId, studentId);
        return courseStudentRepository.existsByCourseIdAndUserId(courseId, studentId);
    }
    
    /**
     * 验证用户是否存在（调用用户服务）
     */
    private boolean validateUserExists(String userId) {
        try {
            System.out.println("[DEBUG] 开始验证用户存在性: " + userId);
            log.info("开始验证用户存在性: {}", userId);
            // 调用用户管理服务验证用户是否存在
            Boolean exists = serviceClient.get("user-management", "/api/users/" + userId + "/exists", Boolean.class);
            System.out.println("[DEBUG] 用户存在性验证结果: userId=" + userId + ", exists=" + exists);
            log.info("用户存在性验证结果: userId={}, exists={}", userId, exists);
            return exists != null && exists;
        } catch (Exception e) {
            System.out.println("[DEBUG] 验证用户存在性失败: " + userId + ", error: " + e.getMessage());
            log.error("验证用户存在性失败: {}", userId, e);
            return false;
        }
    }
}